/// <reference path="../typings/main.d.ts" />
'use strict'
const rp = require('request-promise');
const http = require('http');
const _ = require('lodash');
const fs = require('fs');

class MyBot {
    public static TOKEN = process.env.token;
    constructor() {
    }
    public sendRequest(endpoint:string, data:Object, method:string):PromiseLike<any> {
        return rp({
            url: `https://v.hlyue.com:55502/bot${MyBot.TOKEN}/${endpoint}`,
            method: method,
            body: data,
            json: true,
            rejectUnauthorized: false
        });
    }
}
const bot = new MyBot();
console.log(`token: ${MyBot.TOKEN}`);

function randomId():number {
    return Math.floor(Math.random() * 1e12);
}


async function main() : Promise<void> {
    const response = await bot.sendRequest('getUpdates', {}, 'GET');
    console.log(response);
    const msg = await Promise.all(_.map(response.result, (it:any) => bot.sendRequest('sendMessage', {
        chat_id: it.message.chat.id,
        text: `auto reply to: ${it.message.text}`,
        reply_to_message_id: it.message.message_id
    }, 'POST')));
    console.log(msg);
}

async function setWebHook() : Promise<void> {
    const response = await bot.sendRequest('setWebhook', {
        url: 'https://yun.hlyue.com/telegramAPI'
    }, 'POST');
    console.log(response);
}

const mapping = readMapping();
mapping.forEach((val, key) => {
    console.log(key, ' ', val.join(','));
});

function insertMapping(key:string, val:string, map:Map<string, Array<string>> = mapping) {
    if (map.has(key)) {
        const arr = map.get(key);
        if (arr.indexOf(val) == -1) arr.push(val);
    }
    else map.set(key, [val]);
}

function readMapping() : Map<string, Array<string>> {
    const content:Array<Object> = JSON.parse(fs.readFileSync('./assets/mapping.json', 'utf-8'));
    const mapping = new Map();
    content.forEach((it:any) => insertMapping(it.key, it.value, mapping));
    return mapping;
}

function saveMapping() : void {
    const arr = [];
    mapping.forEach((val, key) => {
        val.forEach(val => arr.push({
            key: key,
            value: val
        }))
    });
    fs.writeFileSync('./assets/mapping.json', JSON.stringify(arr));
}

async function processCommand(command:string) {
    command = command.replace('@RD_testing_bot ', '');
    const cmd = command.substr(0, command.indexOf(' '));
    command.replace(cmd + ' ', '');
    if (cmd === 'set') {
        command = command.replace('set ', '');
        const key = command.substr(0, command.indexOf(' '));
        const val = command.substr(command.indexOf(' ') + 1);
        console.log(key, val);
        if (!_.isEmpty(key) && !_.isEmpty(val)) {
            insertMapping(key, val);
            saveMapping();
        }
    }
}

async function processMessageMapping(message:any) : Promise<void> {
    if (_.isUndefined(message.message) || _.isUndefined(message.message.text)) return;
    const msg = message.message;
    const mid = msg.message_id;
    const cid = msg.chat.id;
    const mtext:string = msg.text;
    if (mtext.indexOf('@RD_testing_bot ') != -1) {
        await processCommand(mtext);
    } else {
        for (let key of mapping.keys()) {
            if (mtext.indexOf(key) != -1) {
                await bot.sendRequest('sendMessage', {
                    chat_id: cid,
                    text: `${key} might be: ${mapping.get(key).join(' or ')}`,
                    reply_to_message_id: mid
                }, 'POST');
            }
        }
    }
}

http.createServer((req, res) => {
    if (req.method === 'POST') {
        let body = '';
        req.on('data', data => body += data);
        req.on('end', () => {
            const json = JSON.parse(body);
            res.end();
            processMessageMapping(json).catch(err => console.log(err));
        });
    } else {
        res.end();
    }
}).listen(8123);

setWebHook().catch(err => console.error(err));
// main().catch(err => console.error(err));
